---
title: NDReimbursement
summary: Non-disabling reimbursement (NDR) statement screen where claims are reviewed, amounts chosen, and payment made by mail or online.
status: generated
owner: SAIF Case Management
last_reviewed: 2026-10-20
---

# NDReimbursement

Policyholders and internal staff use this screen to review the claims on a non-disabling reimbursement (NDR) statement for a policy. External updaters (the policy-holder flag, `IsPolicyHolder`) choose the amount to reimburse for each editable claim, save, and pay either by mail (a PDF statement opens in a new tab) or online (the OneInc payment modal); internal updaters alone do not receive these controls. Internal updaters can also override a statement's due date; a delete confirmation is shown, but its form submits GET and cannot invoke the POST delete handler. It is the only screen in the application and the home page registered in the BOL menu map †.

## Route

The page declares `@page "{handler?}"` and is aliased to the empty route with `Conventions.AddPageRoute("/NDReimbursement", "")`. All URLs sit under the path base `/NDReimbursementWebApp`. Only handlers that render the full page are listed; JSON and file handlers are under [AJAX and grid actions](#ajax-and-grid-actions).

| Page | Handler | Verb | URL | Route parameters | Page model | Layout |
| --- | --- | --- | --- | --- | --- | --- |
| `/NDReimbursement` | `OnGet` | GET | `/NDReimbursementWebApp/` and `/NDReimbursementWebApp/NDReimbursement` | `{handler?}` | `NDReimbursementsModel` (`Pages/NDReimbursement.cshtml.cs`) | `_PolicyLayout` † (set in `Pages/_ViewStart.cshtml`) |
| `/NDReimbursement` | `OnPost` | POST | `/NDReimbursementWebApp/NDReimbursement` | `{handler?}` | `NDReimbursementsModel` | `_PolicyLayout` † |
| `/NDReimbursement` | `OnPostReloadContext` | POST | `/NDReimbursementWebApp/NDReimbursement?handler=ReloadContext` | `{handler?}` | `NDReimbursementsModel` | `_PolicyLayout` † |
| `/NDReimbursement` | `OnPostPolicyNumber` | POST | `/NDReimbursementWebApp/NDReimbursement?handler=PolicyNumber` | `{handler?}` | `NDReimbursementsModel` | `_PolicyLayout` † |
| `/NDReimbursement` | `OnPostStatement` | POST | `/NDReimbursementWebApp/NDReimbursement?handler=Statement` | `{handler?}` | `NDReimbursementsModel` | `_PolicyLayout` † |
| `/NDReimbursement` | `OnPostReimburseAll` | POST | `/NDReimbursementWebApp/NDReimbursement?handler=ReimburseAll` | `{handler?}` | `NDReimbursementsModel` | `_PolicyLayout` † |
| `/NDReimbursement` | `OnPostDueDate` | POST | `/NDReimbursementWebApp/NDReimbursement?handler=DueDate` | `{handler?}` | `NDReimbursementsModel` | `_PolicyLayout` † |
| `/NDReimbursement` | `OnPostDeleteStatement` | POST | `/NDReimbursementWebApp/NDReimbursement?handler=DeleteStatement` | `{handler?}` | `NDReimbursementsModel` | `_PolicyLayout` † |
| `/NDReimbursement` | `OnPostDevAccess` | POST | `/NDReimbursementWebApp/NDReimbursement?handler=DevAccess` (no UI caller; its form is commented out in the view) | `{handler?}` | `NDReimbursementsModel` | `_PolicyLayout` † |

## Access

Requirements are listed from the most general to the most specific. The package that supplies the layout, authentication and base page model is not available in this repository, so its contribution is marked † (package documentation) or ** (unverifiable).

| Requirement | Declared on | Effect |
| --- | --- | --- |
| `[SecurityApiAuthorize("NonDisReimbViewResource,NonDisReimbUpdateResource,NonDisReimbViewExtResource,NonDisReimbUpdateExtResource")]` | `NDReimbursementsModel` | A user needs any one of the four roles to open the screen. The check is a remote Security API call with OR semantics ([INH-009](../application/business-rules.md#inh-009)) †. A failed Security API response throws instead of denying normally ([INH-011](../application/business-rules.md#inh-011)) †. |
| No handler-level authorization attribute | every handler | Each handler's effective roles are the page-level list. |
| `[IgnoreAntiforgeryToken]` | `NDReimbursementsModel` | Anti-forgery validation is **disabled for every POST handler** on the screen. `BolMenuModel` in the base chain also declares `[IgnoreAntiforgeryToken]` †. |
| `[RequestFormLimits(ValueCountLimit = 30000)]` | `NDReimbursementsModel` | Allows large claim tables to be submitted. |
| Role flags computed in `PopulateModel` | `NDReimbursementsModel` | `IsInternalUpdater` (`NonDisReimbUpdateResource`), `IsExternalUpdater` (`NonDisReimbUpdateExtResource`), `IsInternalReadOnly` (`NonDisReimbViewResource`), `IsExternalReadOnly` (`NonDisReimbViewExtResource`), `IsInternalITUser` (`Information Technology Div` or `IT CSI Contractors`) and `CanPrint` (`DocCoreApiUserResource`). The active view consumes only `IsInternalUpdater` (due-date and delete controls) and `IsPolicyHolder`, set from `IsExternalUpdater` (claims-related controls). `IsInternalReadOnly`, `IsExternalReadOnly` and `IsInternalITUser` are not referenced by active view markup (the `IsInternalITUser` reference is commented out), and `CanPrint` is computed but not used by the view or enforced by any handler (TD-APP-004). |
| `IsAuthorizedAsync(ExternalUpdater).Result` | `NDReimbursementsModel` constructor | Sets `IsExternalUpdater` and `ChangeContextPrivilege = !IsExternalUpdater`. The call blocks on an asynchronous check. |
| Not-authorized and invalid-user checks | `NDReimbursementsModel.PopulateModel` | No `CurrentUserId` sets "Invalid User" ([BR-APP-002](../application/business-rules.md#br-app-002)). A user with none of the four NDR roles is ordinarily denied by the page-level `[SecurityApiAuthorize]` gate before `PopulateModel`; the fallback branch, if reached, sets `IsInvalidUser` and "Not Authorized" ([BR-APP-003](../application/business-rules.md#br-app-003)). |
| Policy access validation | `BolPolicyModel` † | Failure sets an error message and `AccessAllowed = false`; the view renders the claims area only when `AccessAllowed` is true ([INH-002](../application/business-rules.md#inh-002)) †. |

### Handler authorization and anti-forgery posture

Every handler inherits the class-level `[IgnoreAntiforgeryToken]`. None of the AJAX or form-driven calls described below sends an anti-forgery token.

| Handler | Verb | Changes state | Anti-forgery | Role enforced on the server | Source |
| --- | --- | --- | --- | --- | --- |
| `OnGet` | GET | no | not applicable | page list † | `Pages/NDReimbursement.cshtml.cs:153-177` |
| `OnPost` | POST | no (reloads the screen) | disabled | page list † | `Pages/NDReimbursement.cshtml.cs:190-193` |
| `OnPostReloadContext` | POST | yes (sets the BOL context policy number and saves the context) | disabled | page list † | `Pages/NDReimbursement.cshtml.cs:182-188` |
| `OnPostPolicyNumber` | POST | no | disabled | page list † | `Pages/NDReimbursement.cshtml.cs:239-254` |
| `OnPostStatement` | POST | no | disabled | page list † | `Pages/NDReimbursement.cshtml.cs:256-270` |
| `OnPostUpdateReimbursements` | POST (JSON) | yes (claim reimbursement amounts) | disabled | page list †; no role check in the handler | `Pages/NDReimbursement.cshtml.cs:196-219` |
| `OnPostPayOnline` | POST (JSON) | yes (creates a OneInc payment request) | disabled | page list †; amount check only | `Pages/NDReimbursement.cshtml.cs:221-237` |
| `OnPostPayByMail` | POST (file) | yes (saves claim amounts, then renders a PDF) | disabled | page list †; no role check in the handler | `Pages/NDReimbursement.cshtml.cs:272-311` |
| `OnPostReimburseAll` | POST | yes (sets every claim to its allowed amount) | disabled | page list †; the button renders only when reimbursable claims exist | `Pages/NDReimbursement.cshtml.cs:313-330` |
| `OnPostDueDate` | POST | yes (overrides the statement due date) | disabled | page list †; no role check in the handler, the form renders only for `IsInternalUpdater` | `Pages/NDReimbursement.cshtml.cs:332-350` |
| `OnPostDownloadStatement` | POST (file) | no (read) | disabled | page list †; `CanPrint` is computed but not enforced | `Pages/NDReimbursement.cshtml.cs:352-390` |
| `OnPostDevAccess` | POST | yes (changes the effective access level) | disabled | page list †; no IT or QA role check | `Pages/NDReimbursement.cshtml.cs:392-406` |
| `OnPostDeleteStatement` | POST | yes (deletes the statement) | disabled | page list †; no role check in the handler, the trigger renders only for `IsInternalUpdater` | `Pages/NDReimbursement.cshtml.cs:408-424` |

Server-side enforcement of the capability flags is absent: the flags only decide what the view renders ([BR-APP-003](../application/business-rules.md#br-app-003)). The security findings that follow from this (CSRF exposure, the developer-access escalation path, the client-supplied audit user name and the client-supplied maximum payment amount) belong on [Tech debt](../application/tech-debt.md).

## Entry conditions
- The empty route `/NDReimbursementWebApp/` reaches this screen through the `AddPageRoute("/NDReimbursement", "")` alias. There is no redirect chain.
- The BOL menu map names the screen as the home page (`BasicAppMap.PageIds.HomePage = "NDReimbursement"`, page id `NDR-NDREIMBURSEMENT`, menu category `NDR`) †.
- The page needs a policy number in the BOL web context. The context resolves from the `BolContext` cookie, the referring application, a `WebContextId` form value or `cid` query value, then session ([INH-001](../application/business-rules.md#inh-001)) †. When no policy is in context the screen shows its no-policy state and no claims.
- Internal users can change the policy in context; external updaters cannot (`ChangeContextPrivilege = !IsExternalUpdater`). For external users the policy associations are filtered by user type ([INH-005](../application/business-rules.md#inh-005)) †.
- A direct URL is accepted if the caller holds one of the four NDR roles.

## Fields

| Field | Binds to | Control | Purpose | Validation |
| --- | --- | --- | --- | --- |
| Policy-number context form (`#reloadContext`) | `WebContext.PolicyNumber` (read from form key `policyNumber`) | hidden form submitted by `refreshPage()` | Reloads the screen for the policy in context | none |
| Due date override (internal updaters only) | form key `dueDate` | jQuery UI date picker | Overrides the statement due date | Client limits only: today through due date + 90 days ([BR-SCR-002](../application/business-rules.md#br-scr-002)); no server check |
| Statement selector | form key `selectedStatement` (`SelectedStatementId`, `decimal?`) | `<select asp-items="Model.SelectStatements">`, submits on change | Chooses which statement is shown | none |
| Claim table: employee, claim number, allowed amount | `SelectedStatementClaims` (`List<NDRClaimModel>`) | read-only table cells | Shows each claim and what is allowed | none |
| Requested amount | `SelectedStatementClaims` item | text input inside `#ReimbursableClaimsContainer` | Amount to reimburse for the claim | Rendered as an input only when the claim is editable (`claim.IsEditable`: due date not passed and allowed amount above zero, [BR-SCR-003](../application/business-rules.md#br-scr-003)) and `Model.IsPolicyHolder` is true (set from `IsExternalUpdater`); otherwise it is not editable. Save, Pay online, Pay by mail and Reimburse all additionally require `HasReimburableClaims`, which needs an editable claim and `IsPolicyHolder`. Handled in `ClaimsTable.js` |
| Policy number column | `Header.Associations` | table column | Shown when the header has policy associations † | none |
| Cash-flow indicator | claim bill code | table indicator | Flags cash-flow claims ([BR-SCR-004](../application/business-rules.md#br-scr-004)) | none |
| Current user (`#cUser`) | posted as `UserName` by `ClaimsTable.js` | hidden input | Audit user name sent with Save | none; the value is client-supplied |
| Totals and notices | `AmountToReimburse` (`decimal?`) | computed text, pending-payment tooltip, "Claims selection and payment must be received by 6:00 p.m." notice, due-date-passed and cash-flow warnings | Summarizes what is payable | none |
| Messages | `ErrorMessage`, `NdrWarningMessage` | message tables in the header region | Reports errors and warnings | none |

No handler checks `ModelState` and no bound property carries a data-annotation validator. The `[BindProperty]` members are `NDReimbursements`, `SelectedStatementId`, `SelectedStatementClaims`, `AmountToReimburse`, `DevAccessLevel`, `IsInvalidUser` and `NdrWarningMessage`. Handlers also read raw form keys `selectedStatement`, `dueDate`, `policyNumber`, `statementId` and `accessRequest`.

## Operations

All delegated callees are internal packages that are not documented by this run. Their behavior is described from call sites in the page model and services, so no link is given and no † is used for them; their internals are unknown**. Only `SaveContext` in `IT.CoreServices.BolMiddleware` carries † because it comes from retrieved package documentation.

| Operation | Trigger | Request | Description | Delegates to |
| --- | --- | --- | --- | --- |
| Load screen for the context policy | Menu entry or direct URL † | `GET /NDReimbursement` | Loads statements for the policy, selects the current statement, builds the claims list and checks for pending online payments. | [Load screen](../application/operations/load-screen.md): call sites of `GetPolicyStatements`, `GetCurrentStatement` (NDReimbursementAPI.Client) and `GetPendingNDROnlinePaymentsAsync` (DigitalPaymentAPIClient) |
| Change policy context | `refreshPage()` submits `#reloadContext` | `POST /NDReimbursement?handler=ReloadContext` | Sets the context policy number, saves the context, then reloads the screen through `OnPost` and `OnPostPolicyNumber`. | [Change policy context](../application/operations/change-policy-context.md): `SaveContext` in `IT.CoreServices.BolMiddleware`† |
| Select statement | `selectedStatement` change | `POST /NDReimbursement?handler=Statement` | Reloads the screen for the chosen statement. | [Load screen](../application/operations/load-screen.md): call site of `GetStatement` (NDReimbursementAPI.Client) |
| Save requested amounts | Save button in the claims table | `POST /NDReimbursement?handler=UpdateReimbursements` | Saves each claim's requested amount. See [AJAX and grid actions](#ajax-and-grid-actions). | [Save requested amounts](../application/operations/save-requested-amounts.md): call site of `UpdateClaimAsync` (NDReimbursementAPI.Client) |
| Reimburse all | `asp-page-handler="ReimburseAll"` button | `POST /NDReimbursement?handler=ReimburseAll` | Sets every requested amount to its allowed amount, saves, and redisplays ([BR-SCR-005](../application/business-rules.md#br-scr-005)). | [Save requested amounts](../application/operations/save-requested-amounts.md): call site of `UpdateClaimAsync` (NDReimbursementAPI.Client) |
| Pay by mail | `asp-page-handler="PayByMail"` button (`formtarget="_blank"`) | `POST /NDReimbursement?handler=PayByMail` | Saves claim amounts, builds the statement XML and returns a PDF in a new tab on success; when the preview payload is not a string or an exception is caught, sets `IsSuccessful` false and `ErrorMessage` and re-renders the page (the message is displayed only if `!IsSuccessful && !HasPolicyNumber` holds). See [AJAX and grid actions](#ajax-and-grid-actions). | [Pay by mail](../application/operations/pay-by-mail.md): call sites of `UpdateClaim`, `GetOnlinePrintStatementXML` (NDReimbursementAPI.Client) and `GeneratePreview` (DocumentsCoreAPI.Client) |
| Pay online | Pay Online button handled by `PaymentModal.js` | `POST /NDReimbursement/PayOnline` | Validates the amount and creates a OneInc payment request that opens the payment modal ([BR-SCR-007](../application/business-rules.md#br-scr-007)). The request is created by `OneIncService.BuildPaymentRequest`, which calls `CreateMakePaymentRequest` on `IOneIncAPIClient` (call site in `Services/OneIncService.cs`; package internals unknown**). If validation fails or the call throws, the handler returns null. | [Pay online](../application/operations/pay-online.md): call site of `CreateMakePaymentRequest` (OneIncAPIClient) in `OneIncService` |
| Download statement | Download form (`formtarget="_blank"`) | `POST /NDReimbursement?handler=DownloadStatement` | Returns the statement as a PDF in a new tab on success (the final PDF byte is dropped, TD-APP-009); when the preview payload is not a string or an exception is caught, sets `IsSuccessful` false and `ErrorMessage` and re-renders the page (the message is displayed only if `!IsSuccessful && !HasPolicyNumber` holds). | [Pay by mail](../application/operations/pay-by-mail.md): same call sites of `GetOnlinePrintStatementXML` (NDReimbursementAPI.Client) and `GeneratePreview` (DocumentsCoreAPI.Client) |
| Override due date | Due-date form (internal updaters) | `POST /NDReimbursement?handler=DueDate` | Parses the entered date and updates the statement due date. | [Override due date](../application/operations/override-due-date.md): call site of `UpdateDueDate` (NDReimbursementAPI.Client) |
| Delete statement | `#deleteStatement` opens the confirmation, then submit | Form submit (GET, no `method="post"`) | The observed form cannot invoke `OnPostDeleteStatement`, so it does not delete the statement from the UI; see [States](#states). The handler (`POST /NDReimbursement?handler=DeleteStatement`) deletes and reloads only for a separately issued POST. | [Delete statement](../application/operations/delete-statement.md): call site of `DeleteStatement` (NDReimbursementAPI.Client) |
| Developer access simulation | None (form commented out); reachable only by direct POST ** | `POST /NDReimbursement?handler=DevAccess` | Reloads the screen with a chosen access type, which forces `IsExternalUpdater` or `IsInternalUpdater` to true. | — |

## Dialogs and partials

Dialogs and partials are part of this screen; none is a screen of its own.

| Name | Opens as | Returned by | Purpose |
| --- | --- | --- | --- |
| Delete confirmation (`.cd-popup`) | Inline popup in `NDReimbursement.cshtml`, opened by `#deleteStatement` (rendered for `IsInternalUpdater` only) | Rendered with the page (`GET /NDReimbursement`) | Confirms deletion before the delete form is submitted. |
| OneInc payment modal (`#portalOneContainer`) | External hosted modal opened by `portalOne.makePayment` using the script at `Model.OneIncScriptUrl` | Payment request JSON from `POST /NDReimbursement/PayOnline` | Collects the online payment. On completion it calls `refreshPage()`. |
| `_MakePaymentModalBase` | Inline `<partial>` tag helper at `Pages/NDReimbursement.cshtml:424` | Rendered with the page | Its `#makepay-modal` markup is not driven by any script because `PaymentModal.js` uses `#portalOneContainer`; treated as orphan markup *. |

## AJAX and grid actions

Each request is attributable to this screen and is documented once on the hosted endpoints page. The two file handlers are form submissions rather than script calls.

| Request | Kind | Called by | Returns |
| --- | --- | --- | --- |
| [`POST /NDReimbursement?handler=UpdateReimbursements`](../application/hosted-endpoints.md#post-ndreimbursementhandlerupdatereimbursements) | named handler JSON (`application/json`, `ReimbursementsUpdate` body); anti-forgery disabled | Save button, `wwwroot/js/ClaimsTable.js:233-236` | `{ success }`; on success the page calls `refreshPage()` |
| [`POST /NDReimbursement?handler=PayOnline`](../application/hosted-endpoints.md#post-ndreimbursementhandlerpayonline) | named handler JSON (form-urlencoded `totalAmount`, `maxAmount`, `policyNum`); anti-forgery disabled | `$.post` in `wwwroot/js/PaymentModal.js:29`, which uses the route-segment form `/NDReimbursement/PayOnline` | OneInc payment request JSON, or null when validation fails |
| [`POST /NDReimbursement?handler=PayByMail`](../application/hosted-endpoints.md#post-ndreimbursementhandlerpaybymail) | file download (`application/pdf`); anti-forgery disabled | Pay by mail button, `Pages/NDReimbursement.cshtml:315` | PDF; the page re-renders on failure |
| [`POST /NDReimbursement?handler=DownloadStatement`](../application/hosted-endpoints.md#post-ndreimbursementhandlerdownloadstatement) | file download (`application/pdf`); anti-forgery disabled | Download form, `Pages/NDReimbursement.cshtml:348-351` | PDF on success; for an invalid preview payload or caught exception, error state is set and the page re-rendered (message display depends on the view condition) |

## Client-side behavior
- **Script module:** `wwwroot/js/NDReimbursementWebApp.js` carries `refreshPage()` (submits `#reloadContext`), the delete popup helpers and the loading helper.
- `ClaimsTable.js`: handles requested-amount inputs, totals and the Save AJAX call. `siteScripts.cshtml` references it as `claimsTable.js`; the case difference is harmless on IIS *.
- `PaymentModal.js`: OneInc `portalOne` integration, reading `policyNum` from `#policy-number-hidden`, which is not in this repository's markup and is presumably supplied by the package layout **.
- `DatePicker.js`: jQuery UI date picker limiting the due-date override window.
- The page loads jQuery UI 1.12.1 and a second copy of jQuery 3.6.0 from a public CDN in its Scripts section, on top of the layout's own scripts †.
- The loading indicator targets `.loadingDiv`, which is not in this repository's markup (package layout **).
- Not used: `ViewDocument.js`, `SaifDropdown.js`, `site.js` (empty), the `DeleteStatement()` function in `NDReimbursementWebApp.js` and the jquery-validation assets under `wwwroot/lib`. The `#declineDelete` click binding in `NDReimbursementWebApp.js:26` is malformed.

## States

| State | Condition |
| --- | --- |
| No policy in context | `HasPolicyNumber` is false; no claims area is rendered. |
| Invalid or unauthorized user | A user without any of the four NDR roles is ordinarily denied by the page-level `[SecurityApiAuthorize]` gate before `PopulateModel` runs. Within `PopulateModel`, a missing `CurrentUserId` sets `ErrorMessage` to "Invalid User" and returns false before `HasPolicyNumber` is assigned, so that property keeps its earlier `OnRequestStart` value derived from `Header`. If the defensive role fallback is reached, it sets `IsInvalidUser` and "Not Authorized" and returns false. The view renders its `ErrorMessage` block only when `!IsSuccessful && !HasPolicyNumber`, so display of either message depends on the pre-existing `HasPolicyNumber` value and is not guaranteed. |
| Access not allowed | `AccessAllowed` is false (declared in the base page model, meaning **); the claims area renders only when `HasPolicyNumber && HasNDR && AccessAllowed` ([BR-SCR-011](../application/business-rules.md#br-scr-011)). |
| Invalid policy | `GetPolicyStatements` throws an HTTP status exception: the handler sets `HasInvalidPolicyNumber` and `ErrorMessage` ("is not a valid policy number" for HTTP 400, a generic retrieval error otherwise) and returns false. The view does not reference `HasInvalidPolicyNumber`, `HasNDR` stays true, and the `ErrorMessage` block renders only when `!IsSuccessful && !HasPolicyNumber`, so the message is not shown by that block when a policy number is present ([BR-SCR-009](../application/business-rules.md#br-scr-009)). |
| No NDR statements | `HasNDR` is false and `NdrWarningMessage` is set; the claims area is not rendered ([BR-SCR-009](../application/business-rules.md#br-scr-009)). |
| Due date passed | Claims are read-only ([BR-SCR-001](../application/business-rules.md#br-scr-001)). |
| Pending online payments | `HasPendingPayOnlinePayments` is true ([BR-SCR-008](../application/business-rules.md#br-scr-008)). |
| Claims saved | `ClaimsSaved` is derived during model population: true when any selected claim has a requested amount greater than 0 and there is no pending online payment. It does not record that a save just occurred. |
| Delete confirmation form | The `<form>` at `Pages/NDReimbursement.cshtml:328` declares `asp-page-handler="DeleteStatement"` but no `method="post"`, so it submits as GET. The only delete handler is `OnPostDeleteStatement` (no `OnGetDeleteStatement` exists), so this form cannot invoke the POST delete handler; the HTTP result of the unmatched GET is **. A POST issued separately to the handler is a different path. |

## Business rules

Screen rules are linked to their entries on the business rules page. Inherited rules carry †.

| Rule ID | Rule | Enforcement | Source |
| --- | --- | --- | --- |
| [BR-SCR-001](../application/business-rules.md#br-scr-001) | The due date is effective at 18:00; once it has passed, claims become read-only (`DueDatePassed`). | Manager logic and page-model state | `src/NDReimbursementWebApp/Managers/NDR/NDReimbursementManager.cs:55`; `src/NDReimbursementWebApp/Pages/NDReimbursement.cshtml.cs:543` |
| [BR-SCR-002](../application/business-rules.md#br-scr-002) | A due-date override must fall between today and the due date + 90 days. Only the UI enforces it. | Client script; the server does not re-check | `src/NDReimbursementWebApp/Pages/NDReimbursement.cshtml.cs:546-548`; `src/NDReimbursementWebApp/wwwroot/js/DatePicker.js` |
| [BR-SCR-003](../application/business-rules.md#br-scr-003) | A claim is editable only when the due date has not passed and its allowed amount is above zero. | Manager logic | `src/NDReimbursementWebApp/Managers/NDR/NDReimbursementManager.cs:5` |
| [BR-SCR-004](../application/business-rules.md#br-scr-004) | A claim is flagged as cash flow when `ReimbursementBillCode == "CF"`. | Manager logic | `src/NDReimbursementWebApp/Managers/NDR/NDReimbursementManager.cs:5` |
| [BR-SCR-005](../application/business-rules.md#br-scr-005) | Reimburse all sets each requested amount to the allowed amount. | Handler logic | `src/NDReimbursementWebApp/Pages/NDReimbursement.cshtml.cs:565-585`; `src/NDReimbursementWebApp/Managers/NDR/NDReimbursementManager.cs:42` |
| [BR-SCR-006](../application/business-rules.md#br-scr-006) | Reimbursable claims exist when claims are editable and either Reimburse all applies or the user is a policyholder. | Handler logic | `src/NDReimbursementWebApp/Pages/NDReimbursement.cshtml.cs:591-605` |
| [BR-SCR-007](../application/business-rules.md#br-scr-007) | Pay online requires `0 < total <= max`. `max` is supplied by the client. | Handler check | `src/NDReimbursementWebApp/Pages/NDReimbursement.cshtml.cs:225-229` |
| [BR-SCR-008](../application/business-rules.md#br-scr-008) | Pending online payments (the NDR flag or a digital-payment count above zero) block the "claims saved" state; a 404 from the digital payment API counts as zero. | Handler logic and `DigitalPaymentService` | `src/NDReimbursementWebApp/Pages/NDReimbursement.cshtml.cs:434-445,608-611`; `src/NDReimbursementWebApp/Services/DigitalPaymentService.cs:19-33` |
| [BR-SCR-009](../application/business-rules.md#br-scr-009) | An HTTP 400 from `GetPolicyStatements` makes the handler set `HasInvalidPolicyNumber` and an error message (the view does not reference that flag or render the message while a policy number is present); when there are no NDR statements `HasNDR` is false. | Handler logic | `src/NDReimbursementWebApp/Pages/NDReimbursement.cshtml.cs:495-513` |
| [BR-SCR-010](../application/business-rules.md#br-scr-010) | The developer-access options depend on the policy number and the selected access type. | Manager logic | `src/NDReimbursementWebApp/Managers/NDR/NDReimbursementManager.cs:92`; `src/NDReimbursementWebApp/Pages/NDReimbursement.cshtml.cs:488` |
| [BR-SCR-011](../application/business-rules.md#br-scr-011) | The claims area renders only when `HasPolicyNumber && HasNDR && AccessAllowed`. | View condition | `src/NDReimbursementWebApp/Pages/NDReimbursement.cshtml:115` |
| [BR-APP-002](../application/business-rules.md#br-app-002) | Without a current user, `PopulateModel` returns false and sets `ErrorMessage` to "Invalid User"; display is subject to the view condition `!IsSuccessful && !HasPolicyNumber` (using the earlier `HasPolicyNumber` value). | Handler check | `src/NDReimbursementWebApp/Pages/NDReimbursement.cshtml.cs:452-457` |
| [BR-APP-003](../application/business-rules.md#br-app-003) | A user with none of the four NDR roles is ordinarily denied by the page-level gate; the `PopulateModel` fallback sets "Not Authorized" and returns false (display depends on the view condition); the capability flags are not enforced by the handlers. | Handler check and UI hiding | `src/NDReimbursementWebApp/Pages/NDReimbursement.cshtml.cs:464-485` |
| [INH-002](../application/business-rules.md#inh-002) | Policy access is validated by the base page model; failure sets `AccessAllowed = false` and the derived page must honor it. † | Inherited, soft enforcement | BolMiddleware, from package documentation |
| [INH-009](../application/business-rules.md#inh-009) | `[SecurityApiAuthorize("A,B")]` grants access with OR semantics through the remote Security API. † | Inherited attribute | SAIF.NetCore.AuthService, from package documentation |

Statement validity, claim updates, due-date updates, deletion and PDF generation for the `Policy_NDR_Statement` package are delegated to the API clients named under [Operations](#operations) and are not rules of this screen.

## Navigation

| Target | Trigger | Parameters |
| --- | --- | --- |
| This screen ([NDReimbursement](ndreimbursement.md)) | Form handlers re-render the screen; `refreshPage()` after a context change, a completed payment or a statement change | Form keys listed under [Fields](#fields) |
| PDF in a new browser tab | Pay by mail or Download statement (`formtarget="_blank"`) | Posted claim amounts or `statementId` |
| Claim profile in the claim profile application (outside this repository) | Claim number link in the claims table | `claimNum`. The path is hard-coded in the view; no configuration key holds it. |
| OneInc hosted payment modal (external) | Pay Online | Payment request returned by `PayOnline` |
| Other applications through the BOL menu and header | Menu click or policy-context switch † | Supplied by the package layout † |

## Screen flow diagram

The diagram shows the navigation targets reachable from the NDReimbursement screen.

```mermaid
flowchart TD
    ndreimbursement["NDReimbursement"]
    pdf["PDF in new tab"]
    claimprofile["Claim profile (other application)"]
    oneinc["OneInc payment modal (external)"]

    ndreimbursement -->|Form post| ndreimbursement
    ndreimbursement -->|Pay by mail or download| pdf
    ndreimbursement -->|Claim number link| claimprofile
    ndreimbursement -->|Pay online| oneinc
    oneinc -->|Payment complete| ndreimbursement
```

---

> [!NOTE]
> Statements marked with `*` are inferred from code patterns. Statements marked with `**` could not be verified from available source. Statements marked with `†` are sourced from package documentation retrieved with the Legends CLI. The four API-client packages (`NDReimbursementAPI.Client`, `DocumentsCoreAPI.Client`, `DigitalPaymentAPIClient`, `OneIncAPIClient`) are internal packages with no retrievable documentation, so their behavior is recorded from call sites only. All six referenced packages are classified internal in the package feed status.

## Sources
- src/NDReimbursementWebApp/Pages/NDReimbursement.cshtml
- src/NDReimbursementWebApp/Pages/NDReimbursement.cshtml.cs
- src/NDReimbursementWebApp/Pages/_ViewStart.cshtml
- src/NDReimbursementWebApp/Pages/Shared/_MakePaymentModalBase.cshtml
- src/NDReimbursementWebApp/Pages/Shared/MiddlewareIncludes/siteScripts.cshtml
- src/NDReimbursementWebApp/Managers/NDR/NDReimbursementManager.cs
- src/NDReimbursementWebApp/Services/DigitalPaymentService.cs
- src/NDReimbursementWebApp/Services/OneIncService.cs
- src/NDReimbursementWebApp/Startup.cs
- src/NDReimbursementWebApp/appsettings.json
- src/NDReimbursementWebApp/wwwroot/js/NDReimbursementWebApp.js
- src/NDReimbursementWebApp/wwwroot/js/ClaimsTable.js
- src/NDReimbursementWebApp/wwwroot/js/PaymentModal.js
- src/NDReimbursementWebApp/wwwroot/js/DatePicker.js
